package com.hue.gulimail.gulimailproduct.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.hue.common.to.SkuReductionTo;
import com.hue.common.to.SpuBoundsTo;
import com.hue.common.to.es.SkuEsModel;
import com.hue.common.utils.R;
import com.hue.gulimail.gulimailproduct.entity.*;
import com.hue.gulimail.gulimailproduct.feign.CouponFeignService;
import com.hue.gulimail.gulimailproduct.feign.SearchFeignService;
import com.hue.gulimail.gulimailproduct.feign.WareFeignService;
import com.hue.gulimail.gulimailproduct.service.*;
import com.hue.gulimail.gulimailproduct.vo.spusavevo.*;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hue.common.utils.PageUtils;
import com.hue.common.utils.Query;

import com.hue.gulimail.gulimailproduct.dao.SpuInfoDao;
import org.springframework.transaction.annotation.Transactional;


/**
 * @author yfq
 */
@Service("spuInfoService")
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private SpuImagesService spuImagesService;
    @Autowired
    private AttrService attrService;
    @Autowired
    private ProductAttrValueService productAttrValueService;
    @Autowired
    private SkuInfoService skuInfoService;
    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private CouponFeignService couponFeignService;
    @Autowired
    private BrandService brandService;
    @Autowired
    private CategoryService categoryService;
    @Autowired
    private WareFeignService wareFeignService;
    @Autowired
    private SearchFeignService searchFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveSpuInfo(SpuSaveVo spuSaveVo) {
        //保存spu的基本信息
        SpuInfoEntity spuInfo = new SpuInfoEntity();
        BeanUtils.copyProperties(spuSaveVo, spuInfo);
        spuInfo.setCreateTime(new Date());
        spuInfo.setUpdateTime(new Date());
        save(spuInfo);

        //保存spu的描述信息
        List<String> decriptList = spuSaveVo.getDecript();
        SpuInfoDescEntity descEntity = new SpuInfoDescEntity();
        descEntity.setSpuId(spuInfo.getId());
        descEntity.setDecript(String.join(",", decriptList));
        spuInfoDescService.save(descEntity);

        //保存spu的图片信息
        List<String> images = spuSaveVo.getImages();
        spuImagesService.saveImages(spuInfo.getId(), images);

        //保存spu的规格参数
        List<BaseAttrs> baseAttrs = spuSaveVo.getBaseAttrs();
        List<ProductAttrValueEntity> productAttrValueEntityList = baseAttrs.stream().map(baseAttr -> {
            ProductAttrValueEntity product = new ProductAttrValueEntity();
            product.setAttrId(baseAttr.getAttrId());
            AttrEntity attr = attrService.getById(baseAttr.getAttrId());
            product.setAttrName(attr.getAttrName());
            product.setAttrValue(baseAttr.getAttrValues());
            product.setQuickShow(baseAttr.getShowDesc());
            product.setSpuId(spuInfo.getId());
            return product;
        }).collect(Collectors.toList());
        productAttrValueService.saveBatch(productAttrValueEntityList);

        //保存spu的积分信息
        SpuBoundsTo spuBoundsTo = new SpuBoundsTo();
        BeanUtils.copyProperties(spuSaveVo.getBounds(), spuBoundsTo);
        spuBoundsTo.setSpuId(spuInfo.getId());
        couponFeignService.saveSpuBounds(spuBoundsTo);

        //保存sku的所有信息
        //1.sku的基本信息
        List<Skus> skus = spuSaveVo.getSkus();
        for (Skus sku : skus) {
            String defaultImage = "";
            for (Images img : sku.getImages()) {
                if (img.getDefaultImg() == 1) {
                    defaultImage = img.getImgUrl();
                }
            }
            //保存sku的基本信息
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            BeanUtils.copyProperties(sku, skuInfoEntity);
            skuInfoEntity.setSpuId(spuInfo.getId());
            skuInfoEntity.setBrandId(spuInfo.getBrandId());
            skuInfoEntity.setCatalogId(spuInfo.getCatalogId());
            skuInfoEntity.setSaleCount(0L);
            skuInfoEntity.setSkuDefaultImg(defaultImage);
            skuInfoService.save(skuInfoEntity);

            //2.保存images信息
            List<Images> imgs = sku.getImages();
            List<SkuImagesEntity> skuImagesEntityList = imgs.stream().map(img -> {
                SkuImagesEntity skuImagesEntity = new SkuImagesEntity();
                BeanUtils.copyProperties(img, skuInfoEntity);
                skuImagesEntity.setSkuId(skuInfoEntity.getSkuId());
                skuImagesEntity.setImgSort(0);
                return skuImagesEntity;
            }).filter(item -> !StringUtils.isEmpty(item.getImgUrl())).collect(Collectors.toList());
            skuImagesService.saveBatch(skuImagesEntityList);

            //3.sku的销售属性
            List<Attr> attrList = sku.getAttr();
            List<SkuSaleAttrValueEntity> attrEntityList = attrList.stream().map(attr -> {
                SkuSaleAttrValueEntity skuSaleAttrValueEntity = new SkuSaleAttrValueEntity();
                BeanUtils.copyProperties(attr, skuSaleAttrValueEntity);
                skuSaleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                skuSaleAttrValueEntity.setAttrSort(0);
                return skuSaleAttrValueEntity;
            }).collect(Collectors.toList());
            skuSaleAttrValueService.saveBatch(attrEntityList);

            //4.sku的优惠满减信息
            SkuReductionTo skuReductionTo = new SkuReductionTo();
            BeanUtils.copyProperties(sku, skuReductionTo);
            skuReductionTo.setSkuId(skuInfoEntity.getSkuId());
            couponFeignService.saveReductionInfo(skuReductionTo);
        }
    }

    @Override
    public PageUtils querySpuInfoPage(Map<String, Object> params) {
        QueryWrapper<SpuInfoEntity> spuInfoWrapper = new QueryWrapper<>();
        String key = (String) params.get("key");
        if (!StringUtils.isEmpty(key)) {
            spuInfoWrapper.and(w -> w.eq("id", key).or().like("spu_name", key));
        }
        String brandId = (String) params.get("brandId");
        if (!StringUtils.isEmpty(brandId)) {
            spuInfoWrapper.eq("brand_id", brandId);
        }
        String catelogId = (String) params.get("catelogId");
        if (!StringUtils.isEmpty(catelogId)) {
            spuInfoWrapper.eq("catalog_id", catelogId);
        }
        String status = (String) params.get("status");
        if (!StringUtils.isEmpty(status)) {
            spuInfoWrapper.eq("publish_status", status);
        }
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                spuInfoWrapper
        );
        return new PageUtils(page);
    }


    @Override
    public void spuUp(Long spuId) {
        //查询出spu对应的所有sku
        List<SkuInfoEntity> skuInfoList = skuInfoService.getSkuInfoListBySpuId(spuId);

        //查询出spu对应的所有attrValue
        List<ProductAttrValueEntity> attrValues = productAttrValueService.getBySpuId(spuId);
        //拿出所有的attr_id
        List<Long> attrValueIds = attrValues.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());
        //过滤attrValueIds中不需要被检索的attr
        Set<Long> ids = attrService.filterAttrIdBySearchType(attrValueIds);
        //遍历attrValues，如果当前attrId在ids中，就封装为SkuEsModel.Attr，不在就删除
        Iterator<ProductAttrValueEntity> iterator = attrValues.iterator();
        List<SkuEsModel.Attr> attrs = new ArrayList<>();
        while (iterator.hasNext()) {
            ProductAttrValueEntity attrValue = iterator.next();
            if (!ids.contains(attrValue.getAttrId())) {
                iterator.remove();
            } else {
                SkuEsModel.Attr attr = new SkuEsModel.Attr();
                BeanUtils.copyProperties(attrValue, attr);
                attrs.add(attr);
            }
        }

        //得到所有的skuIds
        List<Long> skuIds = skuInfoList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        //获取skuIds对应的hasStock
        TypeReference<Map<Long, Boolean>> typeReference = new TypeReference<Map<Long, Boolean>>() {
        };
        Map<Long, Boolean> stock = wareFeignService.hasStock(skuIds).getData(typeReference);

        //创建要封装的数据
        List<SkuEsModel> skuEsModels = skuInfoList.stream().map(skuInfo -> {
            SkuEsModel skuEsModel = new SkuEsModel();
            BeanUtils.copyProperties(skuInfo, skuEsModel);
            skuEsModel.setSkuPrice(skuInfo.getPrice());
            skuEsModel.setSkuImg(skuInfo.getSkuDefaultImg());
            //查询brand
            BrandEntity brand = brandService.getById(skuInfo.getBrandId());
            skuEsModel.setBrandName(brand.getName());
            skuEsModel.setBrandImg(brand.getLogo());
            //查询catalog
            CategoryEntity catalog = categoryService.getById(skuInfo.getCatalogId());
            skuEsModel.setCatalogName(catalog.getName());
            //添加attrs
            skuEsModel.setAttrs(attrs);
            //查询库存
            skuEsModel.setHasStock(stock.get(skuInfo.getSkuId()));
            //查询评分
            skuEsModel.setHotScore(0L);
            return skuEsModel;
        }).collect(Collectors.toList());

        //将商品的信息存储到es中
        R r = searchFeignService.saveProduct(skuEsModels);
        if ((Integer) r.get("code") == 0) {
            //修改商品的上架状态
            SpuInfoEntity spuInfoEntity = new SpuInfoEntity();
            spuInfoEntity.setId(spuId);
            spuInfoEntity.setPublishStatus(1);
            updateById(spuInfoEntity);
        } else {
            //远程调用出现异常
            /*
                feign的调用流程：
                1.构造请求数据，将对象转为json
                2.发送请求进行执行，执行成功后对响应解码
                3.执行请求默认会有重试机制
             */
        }
    }
}
